package gutils

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
)

// CopyFile 复制文件
func CopyFile(src, dst string) error {
	// 判断 dst 所在文件夹是否存在, 不存在则创建
	err := CreateDir(filepath.Dir(dst))
	if err != nil {
		return err
	}

	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	in, err := os.Open(src)
	if err != nil {
		return err
	}
	defer in.Close()

	_, err = io.Copy(out, in)
	return err
}

// CountFile 统计文件行数
func CountFile(fp string) (int, error) {
	f, err := os.Open(fp)
	if err != nil {
		return 0, err
	}

	buf := make([]byte, 32*1024)
	count := 0
	lineSep := []byte{'\n'}

	for {
		c, err := f.Read(buf)
		count += bytes.Count(buf[:c], lineSep)

		switch {
		case err == io.EOF:
			return count, nil

		case err != nil:
			return count, err
		}
	}

}

// CreateDir 创建文件夹
func CreateDir(d string) error {
	_, err := os.Stat(d)
	if os.IsNotExist(err) {
		err = os.MkdirAll(d, 0755)
		if err != nil {
			return err
		}
	}

	return nil
}

// IsFileExists 文件是否存在
func IsFileExists(fp string) bool {
	_, err := os.Stat(fp)
	if err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}

// IsDir 是否是文件夹
func IsDir(fp string) bool {
	fi, err := os.Stat(fp)
	if err != nil {
		return false
	}

	return fi.IsDir()
}

// 判断所给路径是否为文件
func IsFile(path string) bool {
	return !IsDir(path)
}

// 修改文件的三个时间：将 srcFile 的时间修改为 dstFile 的时间
func ChangeFileTime(dstFile, srcFile string) error {
	if !IsFileExists(dstFile) {
		return fmt.Errorf("文件: %s 不存在", dstFile)
	}
	if !IsFileExists(srcFile) {
		return fmt.Errorf("文件: %s 不存在", srcFile)
	}

	cmd := fmt.Sprintf(`touch -amcr %s %s`, dstFile, srcFile)
	_, err := ExecScript(cmd)
	return err
}

// ReadFileLines 读取文件所有行，适合文件不是特别大的场景
func ReadFileLines(fp string) ([]string, error) {
	lines := make([]string, 0)

	fi, err := os.Open(fp)
	if err != nil {
		return nil, err
	}
	defer fi.Close()

	br := bufio.NewReader(fi)
	for {
		content, _, err := br.ReadLine()
		if err == io.EOF {
			break
		}

		lines = append(lines, string(content))
	}

	return lines, nil
}

// GetHomeDir 获取用户主目录
func GetHomeDir() (string, error) {
	u, err := user.Current()
	if err != nil {
		return "", err
	}
	return u.HomeDir, nil
}

// ClearFile 清空文件
func ClearFile(fp string) error {
	fi, err := os.Stat(fp)
	if err != nil {
		return err
	}

	return ioutil.WriteFile(fp, []byte(""), fi.Mode())
}
